/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#include "BlenderMeshLoadImpl.h"

#include "blender.h"
#include "bBlenderFile.h"
#include "bMain.h"

#include "OgreMath.h"
#include "OgreMesh.h"
#include "OgreSubMesh.h"
#include "OgreMaterial.h"
#include "OgreMaterialManager.h"
#include "OgreHardwareBufferManager.h"
#include "OgreSkeletonManager.h"
#include "OgreSkeleton.h"
#include "OgreBone.h"
#include "OgreStringConverter.h"

#include "Logger.h"
#include "BlenderMaterialLoader.h"
#include "BlenderMeshUtil.h"
#include "BlenderDefine.h"
#include "GEngine.h"

namespace GNgine
{
	static Ogre::uint PackColor(Blender::MCol col, bool _opengl)
	{
		union
		{
			Blender::MCol col;
			Ogre::uint integer;
			unsigned char cp[4];
		} out_color, in_color;

		in_color.col= col;
		if (_opengl) {
			// abgr
			out_color.cp[0]= in_color.cp[3]; // red
			out_color.cp[1]= in_color.cp[2]; // green
			out_color.cp[2]= in_color.cp[1]; // blue
			out_color.cp[3]= in_color.cp[0]; // alpha
		}else{
			 // argb
			// vertex buffer is packed with VET_COLOUR_ABGR, swap b,r
			out_color.cp[2]= in_color.cp[3]; // red
			out_color.cp[1]= in_color.cp[2]; // green
			out_color.cp[0]= in_color.cp[1]; // blue
			out_color.cp[3]= in_color.cp[0]; // alpha
		}
		return out_color.integer;
	}

	BlenderMeshLoadImpl::BlenderMeshLoadImpl(bParse::bBlenderFile* blenderFile,Blender::Object *object, Ogre::Mesh *mesh) 
		: _bFile(blenderFile),_bObject(object), _mesh(mesh),_loader(0),_bMesh(0),_bMcol(0),_materialIndex(0)
	{
		assert(blenderFile);
		assert(object);
		assert(mesh);
		for(int i=0;i<8;i++){
			_bLayers[i]=0;
		}
		_opengl=GNgEngine.useOpengl();
	}

	/*
	loop through face,each face have vertex _boneIndices into vertex buffer
	color in uv layer(total 8 _bLayers?)
	*/
	void BlenderMeshLoadImpl::load(void)
	{
		_bMesh=static_cast<Blender::Mesh*>(_bObject->data);
		assert(_bMesh);

		if(!_bMesh->mface||!_bMesh->mvert){
			GNgLog.out("Skipping mesh %s, it has no usable data", _bMesh->id.name);
			return;
		}
		if((_bMesh->totvert)>LIMIT){
			GNgLog.out("Maximum vertex limit exceeded (%i)",LIMIT);
			return;
		}

		// notify that sorting based in materials

		_loader=new BlenderLoadUtil(_bFile);
		// Find Uv _bLayers
		_loader->getLayers(_bMesh,(Blender::MTFace**)_bLayers,&_bMcol,_validLayers);
		
		//set up skeleton
		if(_bObject->parent&&_bObject->parent->type==OB_ARMATURE){
			_boneIndices.resize(_bMesh->totvert);
			Ogre::SkeletonPtr skel=Ogre::SkeletonManager::getSingleton().load(BLENDER_IDNAME(_bObject->parent),_mesh->getGroup());
			if(!skel.isNull()){
				convertSkeleton(skel.getPointer(),_boneAssignments,_boneIndices);//get skeleton bone _boneIndices
			}
		}
		
		/// parse all faces and convert
		for(int faceIndex=0;faceIndex<_bMesh->totface;faceIndex++){
			convertMeshFace(faceIndex);//add mesh data into _submeshBuffer
		}

		// extra setup of parent is an armature
		if (!_skeletonName.empty()){
			_mesh->setSkeletonName(_skeletonName);
		}

		createMesh();
	}

	void BlenderMeshLoadImpl::createMesh()
	{
		int size=_submeshBuffer.size();
		if(size<=0){
			return;
		}
		
		SubMeshItem* item=_submeshBuffer.getItem(0);
		assert(item);
		_minAABB=_maxAABB=Ogre::Vector3(item->vbuf[0].vertex);
		_radiusAABB=_minAABB.squaredLength();

		for(int i=0;i<size;i++){
			createSubMeshMaterial(i);
			createSubMesh(i);
		}

		/// clear temp
		_submeshBuffer.clear();
		_mesh->_setBounds(Ogre::AxisAlignedBox(_minAABB,_maxAABB),false);
		_mesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(_radiusAABB));

	}

	void BlenderMeshLoadImpl::createSubMeshMaterial(int index)
	{
		SubMeshItem* item=_submeshBuffer.getItem(index);
		SubMeshSlot* slot=_submeshBuffer.getSlot(index);
		Ogre::SubMesh* submesh=item->submesh;
		//Convert blender material
		Blender::Material *mat=_loader->getMaterial(_bObject,slot->material_nr+1);
		/// naming scheme
		/// OB + / + MA + / unique count
		Ogre::String materialName=_mesh->getName()+"/";
		materialName+=Ogre::String(mat?BLENDER_IDNAME(mat):"NULL")+"/";
		materialName+=Ogre::StringConverter::toString(_materialIndex++);
		if(Ogre::MaterialManager::getSingleton().resourceExists(materialName)){
			Ogre::MaterialManager::getSingleton().unload(materialName);
			Ogre::MaterialManager::getSingleton().remove(materialName);
		}
		
		//convert blender material to ogre
		Ogre::MaterialPtr ptr=Ogre::MaterialManager::getSingleton().create(materialName,_mesh->getGroup());
		BlenderMaterialLoader materialLoader(_mesh->getGroup(),_bFile);
		materialLoader.setOgreMaterialDefault(ptr,(slot->mode & TF_LIGHT) != 0,slot->mode,slot->alpha);

		/// slot.tpage will be in the uv chanel,so it's in it's own layer
		for(int i=0;i<8;i++){
			Blender::Image *bImage=slot->tpage[i];
			if(bImage){
				materialLoader.addTextureUnit(ptr,bImage,i);
			}
		}
		
		submesh->setMaterialName(materialName);

	}

	void BlenderMeshLoadImpl::findWeight(int index, SubMeshItem* item)
	{
		BoneAssignListMap::iterator it=_boneAssignments.find(item->vbuf[index].vba_index);
		if(it==_boneAssignments.end()){
			return;
		}
		BoneAssignList list=it->second;
		for(int i=0;i<list.size();i++){
			Ogre::VertexBoneAssignment vba=list[i];
			vba.vertexIndex=index;
			item->submesh->useSharedVertices?_mesh->addBoneAssignment(vba):
				item->submesh->addBoneAssignment(vba);
		}
	}


	int BlenderMeshLoadImpl::createVertexDeclaration(Ogre::SubMesh* submesh)
	{
		int offset=0;
		/// fill in the declaration
		Ogre::VertexDeclaration* decl=submesh->vertexData->vertexDeclaration;
		///position
		decl->addElement(0,offset,Ogre::VET_FLOAT3,Ogre::VES_POSITION);
		offset+=Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

		///no blending wights
		//normal
		decl->addElement(0,offset,Ogre::VET_FLOAT3,Ogre::VES_NORMAL);
		offset+=Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

		//diffuse color
		decl->addElement(0,offset,Ogre::VET_COLOUR_ABGR,Ogre::VES_DIFFUSE);
		offset+=Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR_ABGR);
		/// no specular color
		/// texture coordinates
		for (int layer= 0; layer < _validLayers; layer++){
			decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, layer);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
		}

		return offset;
	}

	void BlenderMeshLoadImpl::createSubMesh(int index)
	{
		
		SubMeshItem* item=_submeshBuffer.getItem(index);
		Ogre::SubMesh* submesh=item->submesh;

		submesh->vertexData=new Ogre::VertexData();
		submesh->vertexData->vertexCount=item->vbuf.size();
		submesh->useSharedVertices=false;
		submesh->operationType=Ogre::RenderOperation::OT_TRIANGLE_LIST;

		
		int vertexSize=createVertexDeclaration(submesh);

		/// the initial vertex buffer
		Ogre::HardwareVertexBufferSharedPtr vertexBuf= Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
		vertexSize,submesh->vertexData->vertexCount,Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

		///bind the source
		Ogre::VertexBufferBinding* bind=submesh->vertexData->vertexBufferBinding;
		bind->setBinding(0,vertexBuf);

		///index  buffer
		int indexSize=item->ibuf.size()*3;

		Ogre::HardwareIndexBuffer::IndexType bufType=(indexSize>65536)?
		Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT;
		Ogre::HardwareIndexBufferSharedPtr indexBuf=Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
		bufType,indexSize,Ogre::HardwareBuffer::HBU_WRITE_ONLY);

		submesh->indexData->indexCount=indexSize;
		submesh->indexData->indexBuffer=indexBuf;

		///build index items
		bool is32bit=bufType==Ogre::HardwareIndexBuffer::IT_32BIT;
		Ogre::uint* indices32=0;
		unsigned short* indices16=0;
		if(is32bit){
			indices32=static_cast<Ogre::uint*>(indexBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
		}else{
			indices16=static_cast<unsigned short*>(indexBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
		}

		int elementSize=item->ibuf.size();
		for(int i=0;i<elementSize;i++){
			MeshFaceIndex faceIndex=item->ibuf[i];
			if (is32bit){
			*indices32++= (Ogre::uint)faceIndex.v1;
			*indices32++= (Ogre::uint)faceIndex.v2;
			*indices32++= (Ogre::uint)faceIndex.v3;
			}else{
			*indices16++= (unsigned short)faceIndex.v1;
			*indices16++= (unsigned short)faceIndex.v2;
			*indices16++= (unsigned short)faceIndex.v3;
			}

			if (!_skeletonName.empty()){
				findWeight((int)faceIndex.v1, item);
				findWeight((int)faceIndex.v2, item);
				findWeight((int)faceIndex.v3, item);
			}
		}

		indexBuf->unlock();

		/// build vertex items
		unsigned char* vertexdata=static_cast<unsigned char*>(vertexBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
		Ogre::VertexData* vdata=submesh->vertexData;
		Ogre::VertexDeclaration* decl=vdata->vertexDeclaration;
		Ogre::VertexDeclaration::VertexElementList elements=decl->findElementsBySource(0);
		float* floatdata=0;
		elementSize=item->vbuf.size();
		for(int i=0;i<elementSize;i++){
		MeshVertex& v=item->vbuf[i];
		int layerCnt=0;
		int texcoordOffset=0;
		Ogre::VertexDeclaration::VertexElementList::const_iterator it=elements.begin(),itEnd=elements.end();
		for(;it!=itEnd;++it){
			Ogre::VertexElement vertexElement=(*it);
			int sematic=vertexElement.getSemantic();
			if(sematic==Ogre::VES_POSITION){
				vertexElement.baseVertexPointerToElement(vertexdata,&floatdata);
				Ogre::Vector3 pos=Ogre::Vector3(v.vertex);
				*floatdata++= pos.x;
				*floatdata++= pos.y;
				*floatdata++= pos.z;

				_minAABB.makeFloor(pos);
				_maxAABB.makeCeil(pos);
				_radiusAABB= std::max(pos.squaredLength(), _radiusAABB);

			}else if(sematic==Ogre::VES_NORMAL){
				vertexElement.baseVertexPointerToElement(vertexdata,&floatdata);
				*floatdata++= v.normal[0];
				*floatdata++= v.normal[1];
				*floatdata++= v.normal[2];
			}else if(sematic== Ogre::VES_TEXTURE_COORDINATES){
				vertexElement.baseVertexPointerToElement(vertexdata, &floatdata);

				layerCnt= GDK3D_Clamp(layerCnt, 0, 7);
				*floatdata++= v.uv[layerCnt][0];
				*floatdata++= 1.f - v.uv[layerCnt][1];

				layerCnt ++;
			}else if(sematic==Ogre::VES_DIFFUSE){
				Ogre::uint *intdata= 0;
				vertexElement.baseVertexPointerToElement(vertexdata, &intdata);
				*intdata++=v.colour;
			}
		}
		vertexdata+=vertexBuf->getVertexSize();
		}

		vertexBuf->unlock();
		if (!_skeletonName.empty()){
			Ogre::VertexDeclaration *newDecl=decl->getAutoOrganisedDeclaration(true,true);
			vdata->reorganiseBuffers(newDecl);
		}
	}

	void BlenderMeshLoadImpl::convertMeshFace(int faceIndex)
	{
		Blender::MFace& face=_bMesh->mface[faceIndex];
		if(!face.v3){
			return;
		}

		SubMeshSlot slot;
		slot.material_nr=face.mat_nr;
		slot.mode=0;
		slot.alpha=0;

		bool isQuad=face.v4!=0;

		MeshFace tri[2]={MeshFace(),MeshFace()};//face need to split to
		if(isQuad){
			splitQuadFace(faceIndex,tri);
		}else{
			addTriFace(faceIndex,tri);
		}

		if (_bLayers[0] != 0){
			slot.mode= _bLayers[0][faceIndex].mode;//submesh mode is in layer data
			slot.alpha= _bLayers[0][faceIndex].transp;//blender layer manage render mode and alpha?
		}

		/// tpage objects
		if (_bLayers[0] != 0) slot.tpage[0]= _bLayers[0][faceIndex].tpage;
		if (_bLayers[1] != 0) slot.tpage[1]= _bLayers[1][faceIndex].tpage;
		if (_bLayers[2] != 0) slot.tpage[2]= _bLayers[2][faceIndex].tpage;
		if (_bLayers[3] != 0) slot.tpage[3]= _bLayers[3][faceIndex].tpage;
		if (_bLayers[4] != 0) slot.tpage[4]= _bLayers[4][faceIndex].tpage;
		if (_bLayers[5] != 0) slot.tpage[5]= _bLayers[5][faceIndex].tpage;
		if (_bLayers[6] != 0) slot.tpage[6]= _bLayers[6][faceIndex].tpage;
		if (_bLayers[7] != 0) slot.tpage[7]= _bLayers[7][faceIndex].tpage;

		SubMeshItem* item= _submeshBuffer.add(slot,_mesh,_bMesh->totface,_bMesh->totvert);
		assert(item);
		
		tri[0].setMaxLayer(_validLayers);
		if(isQuad){
			tri[1].setMaxLayer(_validLayers);
		}

		if(!(face.flag& ME_SMOOTH)){
			tri[0].calcNormal();
			if(isQuad){
				tri[1].calcNormal();
			}
		}

		item->addTri(tri[0]);
		if(isQuad){
			item->addTri(tri[1]);
		}

		if(_bMcol!=0){
			_bMcol+=4;
		}
	}

	
	void BlenderMeshLoadImpl::addTriFace(int faceIndex,MeshFace* tri)
	{
		/// normal (0,1,2)
		Blender::MFace& face=_bMesh->mface[faceIndex];
		Blender::MVert* mvert=_bMesh->mvert;
		Ogre::uint vcol[3]= {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
		if (_bMcol != 0){
			vcol[0]= PackColor(_bMcol[0], _opengl);
			vcol[1]= PackColor(_bMcol[1], _opengl);
			vcol[2]= PackColor(_bMcol[2], _opengl);
		}

		Blender::MVert verts[3];
		verts[0]= mvert[face.v1];
		verts[1]= mvert[face.v2];
		verts[2]= mvert[face.v3];

		tri[0].addVertex(0, VEC2F(verts[0].co)); tri[0].addVertex(1, VEC2F(verts[1].co)); tri[0].addVertex(2, VEC2F(verts[2].co));
		tri[0].addNormal(0, verts[0].no); tri[0].addNormal(1, verts[1].no); tri[0].addNormal(2, verts[2].no);
		tri[0].addColour(0, vcol[0]); tri[0].addColour(1, vcol[1]); tri[0].addColour(2, vcol[2]);
		tri[0].addIndex(0, face.v1); tri[0].addIndex(1, face.v2); tri[0].addIndex(2, face.v3);

		for (int i= 0; i < _validLayers; i++){
			if (_bLayers[i] != 0){
				tri[0].addUvCord(0, i, (float*)_bLayers[i][faceIndex].uv[0]);
				tri[0].addUvCord(1, i, (float*)_bLayers[i][faceIndex].uv[1]);
				tri[0].addUvCord(2, i, (float*)_bLayers[i][faceIndex].uv[2]);
			}
		}
		if (!_boneIndices.empty()){
			tri[0].addVertexBoneAssignment(0, _boneIndices[face.v1]);
			tri[0].addVertexBoneAssignment(1, _boneIndices[face.v2]);
			tri[0].addVertexBoneAssignment(2, _boneIndices[face.v3]);
		}
	}


	void BlenderMeshLoadImpl::splitQuadFace(int faceIndex,MeshFace* tri)
	{
		Blender::MFace& face=_bMesh->mface[faceIndex];
		Blender::MVert* mvert=_bMesh->mvert;
		Ogre::uint vcol[4]={0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
		if(_bMcol!=0){
			vcol[0]=PackColor(_bMcol[0],_opengl);
			vcol[1]=PackColor(_bMcol[1],_opengl);
			vcol[2]=PackColor(_bMcol[2],_opengl);
			vcol[3]=PackColor(_bMcol[3],_opengl);
		}
		
		Blender::MVert verts[4];
		verts[0]=mvert[face.v1];
		verts[1]=mvert[face.v2];
		verts[2]=mvert[face.v3];
		verts[3]=mvert[face.v4];
		
		float va[3],vb[3];
		VEC3SUB2(verts[0].co,verts[1].co,va);
		VEC3SUB2(verts[2].co,verts[3].co,vb);

		float vael=VEC3DOT(va);
		float vbel=VEC3DOT(vb);

		//split to tri (0,1,2) (2,3,0)
		if(vael<vbel){
			tri[0].addVertex(0, VEC2F(verts[0].co)); tri[0].addVertex(1, VEC2F(verts[1].co)); tri[0].addVertex(2, VEC2F(verts[2].co));
			tri[1].addVertex(0, VEC2F(verts[2].co)); tri[1].addVertex(1, VEC2F(verts[3].co)); tri[1].addVertex(2, VEC2F(verts[0].co));

			tri[0].addNormal(0, verts[0].no); tri[0].addNormal(1, verts[1].no); tri[0].addNormal(2, verts[2].no);
			tri[1].addNormal(0, verts[2].no); tri[1].addNormal(1, verts[3].no); tri[1].addNormal(2, verts[0].no);
			
			//from layer
			tri[0].addColour(0, vcol[0]); tri[0].addColour(1, vcol[1]); tri[0].addColour(2, vcol[2]);
			tri[1].addColour(0, vcol[2]); tri[1].addColour(1, vcol[3]); tri[1].addColour(2, vcol[0]);
			
			//_boneIndices from face
			tri[0].addIndex(0, face.v1); tri[0].addIndex(1, face.v2); tri[0].addIndex(2, face.v3);
			tri[1].addIndex(0, face.v3); tri[1].addIndex(1, face.v4); tri[1].addIndex(2, face.v1);

			for(int i=0;i<_validLayers;i++){
				if (_bLayers[i] != 0){
					tri[0].addUvCord(0, i, (float*)_bLayers[i][faceIndex].uv[0]);
					tri[0].addUvCord(1, i, (float*)_bLayers[i][faceIndex].uv[1]);
					tri[0].addUvCord(2, i, (float*)_bLayers[i][faceIndex].uv[2]);

					tri[1].addUvCord(0, i, (float*)_bLayers[i][faceIndex].uv[2]);
					tri[1].addUvCord(1, i, (float*)_bLayers[i][faceIndex].uv[3]);
					tri[1].addUvCord(2, i, (float*)_bLayers[i][faceIndex].uv[0]);
				}

				if (!_boneIndices.empty()){
					tri[0].addVertexBoneAssignment(0, _boneIndices[face.v1]);
					tri[0].addVertexBoneAssignment(1, _boneIndices[face.v2]);
					tri[0].addVertexBoneAssignment(2, _boneIndices[face.v3]);

					tri[1].addVertexBoneAssignment(0, _boneIndices[face.v3]);
					tri[1].addVertexBoneAssignment(1, _boneIndices[face.v4]);
					tri[1].addVertexBoneAssignment(2, _boneIndices[face.v1]);
				}
			}
		}else{/// split to tri (0,1,3) (3,1,2)
			tri[0].addVertex(0, VEC2F(verts[0].co)); tri[0].addVertex(1, VEC2F(verts[1].co)); tri[0].addVertex(2, VEC2F(verts[3].co));
			tri[1].addVertex(0, VEC2F(verts[3].co)); tri[1].addVertex(1, VEC2F(verts[1].co)); tri[1].addVertex(2, VEC2F(verts[2].co));

			tri[0].addNormal(0, verts[0].no); tri[0].addNormal(1, verts[1].no); tri[0].addNormal(2, verts[3].no);
			tri[1].addNormal(0, verts[3].no); tri[1].addNormal(1, verts[1].no); tri[1].addNormal(2, verts[2].no);

			tri[0].addColour(0, vcol[0]); tri[0].addColour(1, vcol[1]); tri[0].addColour(2, vcol[3]);
			tri[1].addColour(0, vcol[3]); tri[1].addColour(1, vcol[1]); tri[1].addColour(2, vcol[2]);

			tri[0].addIndex(0, face.v1); tri[0].addIndex(1, face.v2); tri[0].addIndex(2, face.v4);
			tri[1].addIndex(0, face.v4); tri[1].addIndex(1, face.v2); tri[1].addIndex(2, face.v3);

			for (int i= 0; i < _validLayers; i++){
				if (_bLayers[i] != 0){
					tri[0].addUvCord(0, i, (float*)_bLayers[i][faceIndex].uv[0]);
					tri[0].addUvCord(1, i, (float*)_bLayers[i][faceIndex].uv[1]);
					tri[0].addUvCord(2, i, (float*)_bLayers[i][faceIndex].uv[3]);

					tri[1].addUvCord(0, i, (float*)_bLayers[i][faceIndex].uv[3]);
					tri[1].addUvCord(1, i, (float*)_bLayers[i][faceIndex].uv[1]);
					tri[1].addUvCord(2, i, (float*)_bLayers[i][faceIndex].uv[2]);
				}
			}
			if (!_boneIndices.empty()){
				tri[0].addVertexBoneAssignment(0, _boneIndices[face.v1]);
				tri[0].addVertexBoneAssignment(1, _boneIndices[face.v2]);
				tri[0].addVertexBoneAssignment(2, _boneIndices[face.v4]);

				tri[1].addVertexBoneAssignment(0, _boneIndices[face.v4]);
				tri[1].addVertexBoneAssignment(1, _boneIndices[face.v2]);
				tri[1].addVertexBoneAssignment(2, _boneIndices[face.v3]);
			}
		}
	}

	void BlenderMeshLoadImpl::convertSkeleton(Ogre::Skeleton *skel, BoneAssignListMap &assignList,  BoneAssignIndexList& indexList)
	{
		Blender::Mesh* bMesh=(Blender::Mesh*)_bObject->data;
		if(!bMesh->dvert){
			return;
		}
		_skeletonName=skel->getName();

		unsigned short bones=skel->getNumBones();
		for(unsigned short b=0;b<bones;b++){
			Ogre::Bone* bone=skel->getBone(b);
			int index=_loader->getDeformGroupIndex(_bObject,bone->getName().c_str());
			Blender::MDeformVert *dvert=bMesh->dvert;
			for(int n=0;n<bMesh->totvert;n++,++dvert){
				for(int w=0;w<dvert->totweight;w++){
					if(dvert->dw[w].def_nr==index){
						Ogre::Real weight=dvert->dw[w].weight;
						if(weight>0&&weight>std::numeric_limits<Ogre::Real>::epsilon()){
							Ogre::VertexBoneAssignment vba;
							vba.vertexIndex=0;
							vba.boneIndex=bone->getHandle();
							vba.weight=dvert->dw[w].weight;
							assignList[n].push_back(vba);
							indexList[n]=n;
						}
					}
				}
			}
		}
	}

}
